<template>
    <div class="preview-page">
      <home-header />
      <div class="preview-content">
        <div class="toolbar">
          <el-tooltip content="导入谱子" placement="bottom">
            <el-button circle @click="onOpen"><svg class="icon" aria-hidden="true"><use :xlink:href="'#icon-folderopen'"></use></svg></el-button>
          </el-tooltip>
          <el-divider direction="vertical" class="toolbar-divider" />
          <el-tooltip :content="isRecording ? '停止录音' : '开始录音'" placement="bottom">
            <el-button 
              circle 
              @click="toggleRecording"
              class="record-button"
              :class="{ 'recording': isRecording }"
            >
              <i :class="isRecording ? 'el-icon-video-pause' : 'el-icon-microphone'" class="record-icon"></i>
            </el-button>
          </el-tooltip>
        </div>
        <ScoreEditor 
          ref="scoreEditor" 
          class="preview-score preview-mode" 
          :currentSymbol="currentSymbol" 
          :currentChord="currentChord"
          :enableKeyboardPlayback="true"
          :enableEdit="false"
          :showHighlight="true"
          @notePlayed="handleNotePlayed"
        />
        <div class="keyboard-box">
          <div class="piano-bottom">
            <div class="piano">
              <div v-for="(key, index) in pianoKeys" :key="index" 
                   :id="key"
                   :data-id="key"
                   class="piano-key"
                   :class="{ 'black': key.includes('#') || key.includes('b') }"
                   @click="handlePianoKeyClick(index)">
                <span v-if="noteNames[index]" :class="noteNames[index].pitch">
                  {{ noteNames[index].name }}
                </span>
              </div>
            </div>
            <ul class="piano-group">
              <li v-for="(width, index) in groupWidths" 
                  :key="index" 
                  class="group"
                  :style="{ width: width }">
                {{ index + 1 }}组
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </template>
  
  <script>
  import HomeHeader from '@/components/HomeHeader.vue'
  import ScoreEditor from '@/components/ScoreEditor.vue'
  import RecordRTC from 'recordrtc'
  import * as lamejs from 'lamejs'
  
  export default {
    name: 'PreviewView',
    components: {
      HomeHeader,
      ScoreEditor
    },
    data() {
      return {
        currentSymbol: {
          duration: '四分音符',
          pitch: '小字组'
        },
        currentChord: null,
        domain: window.location.href.indexOf('localhost') !== -1 || window.location.href.indexOf('127.0.0.1') !== -1 
          ? "http://127.0.0.1:5500" 
          : "http://mainbao.gitee.io/pianosystem1",
        isCompute: false,
        intervalList: [],
        intervals: ["", "小二度", "大二度", "小三度", "大三度", "纯四度", "增四度", "纯五度", '小六度', '大六度', '小七度', '大七度', '八度', '1个八度+小二度', '1个八度+大二度'],
        functionKeys: [
          { key: "Esc", code: "27" },
          { key: "F1", code: "112" },
          { key: "F2", code: "113" },
          { key: "F3", code: "114" },
          { key: "F4", code: "115" },
          { key: "F5", code: "116" },
          { key: "F6", code: "117" },
          { key: "F7", code: "118" },
          { key: "F8", code: "119" },
          { key: "F9", code: "120" },
          { key: "F10", code: "121" },
          { key: "F11", code: "122" },
          { key: "F12", code: "123" }
        ],
        mainKeyboard: [
          { key: "`", code: "192" }, { key: "1", code: "49" }, { key: "2", code: "50" }, { key: "3", code: "51" }, { key: "4", code: "52" }, { key: "5", code: "53" }, { key: "6", code: "54" }, { key: "7", code: "55" }, { key: "8", code: "56" }, { key: "9", code: "57" }, { key: "0", code: "48" }, { key: "-", code: "189" }, { key: "+", code: "187" }, { key: "back", code: "8" },
          { key: "Tab", code: "9" }, { key: "Q", code: "81", pianoKey: '51' }, { key: "W", code: "87", pianoKey: '53' }, { key: "E", code: "69", pianoKey: '55' }, { key: "R", code: "82", pianoKey: '56' }, { key: "T", code: "84", pianoKey: '58' }, { key: "Y", code: "89", pianoKey: '60' }, { key: "U", code: "85", pianoKey: '62' }, { key: "I", code: "73" }, { key: "O", code: "79" }, { key: "P", code: "80" }, { key: "{", code: "219" }, { key: "}", code: "221" }, { key: "\\", code: "220" },
          { key: "Lock", code: "20" }, { key: "A", code: "65", pianoKey: '39' }, { key: "S", code: "83", pianoKey: '41' }, { key: "D", code: "68", pianoKey: '43' }, { key: "F", code: "70", pianoKey: '44' }, { key: "G", code: "71", pianoKey: '46' }, { key: "H", code: "72", pianoKey: '48' }, { key: "J", code: "74", pianoKey: '50' }, { key: "K", code: "75" }, { key: "L", code: "76" }, { key: ";", code: "186" }, { key: "\"", code: "222" }, { key: "Enter", code: "13", colspan2: true },
          { key: "Shift", code: "16", colspan2: true }, { key: "Z", code: "90", pianoKey: '27' }, { key: "X", code: "88", pianoKey: '29' }, { key: "C", code: "67", pianoKey: '31' }, { key: "V", code: "86", pianoKey: '32' }, { key: "B", code: "66", pianoKey: '34' }, { key: "N", code: "78", pianoKey: '36' }, { key: "M", code: "77", pianoKey: '38' }, { key: "<", code: "188" }, { key: ">", code: "190" }, { key: "?", code: "191" }, { key: "Shift", code: "16", colspan2: true },
          { key: "Ctrl", code: "17" }, { key: "win", code: "91" }, { key: "alt", code: "18" }, { key: "blank", code: "32", colspan9: true }, { key: "alt", code: "18" }, { key: "Ctrl", code: "17" }
        ],
        numpad: [
          { key: "Num", code: "144" }, { key: "/", code: "111" }, { key: "*", code: "106" }, { key: "-", code: "109" },
          { key: "7", code: "103" }, { key: "8", code: "104" }, { key: "9", code: "105" }, { key: "+", code: "107", rowspan2: true },
          { key: "4", code: "100" }, { key: "5", code: "101" }, { key: "6", code: "102" },
          { key: "1", code: "97" }, { key: "2", code: "98" }, { key: "3", code: "99" }, { key: "Enter", code: "13", rowspan2: true }, { key: "0", code: "96" },
          { key: ".", code: "110" },
        ],
        audioContext: null,
        audioStream: null,
        tracks: [],
        activeDivs: [],
        audioMap: {},
        midiAccess: null,
        lastProcessedTime: 0,
        currentScale: "C 调",
        pianoKeys: [
          'A0', 'A#0/Bb0', 'B0',
          'C1', 'C#1/Db1', 'D1', 'D#1/Eb1', 'E1', 'F1', 'F#1/Gb1', 'G1', 'G#1/Ab1',
          'A1', 'A#1/Bb1', 'B1',
          'C2', 'C#2/Db2', 'D2', 'D#2/Eb2', 'E2', 'F2', 'F#2/Gb2', 'G2', 'G#2/Ab2',
          'A2', 'A#2/Bb2', 'B2',
          'C3', 'C#3/Db3', 'D3', 'D#3/Eb3', 'E3', 'F3', 'F#3/Gb3', 'G3', 'G#3/Ab3',
          'A3', 'A#3/Bb3', 'B3',
          'C4', 'C#4/Db4', 'D4', 'D#4/Eb4', 'E4', 'F4', 'F#4/Gb4', 'G4', 'G#4/Ab4',
          'A4', 'A#4/Bb4', 'B4',
          'C5', 'C#5/Db5', 'D5', 'D#5/Eb5', 'E5', 'F5', 'F#5/Gb5', 'G5', 'G#5/Ab5',
          'A5', 'A#5/Bb5', 'B5',
          'C6', 'C#6/Db6', 'D6', 'D#6/Eb6', 'E6', 'F6', 'F#6/Gb6', 'G6', 'G#6/Ab6',
          'A6', 'A#6/Bb6', 'B6',
          'C7', 'C#7/Db7', 'D7', 'D#7/Eb7', 'E7', 'F7', 'F#7/Gb7', 'G7', 'G#7/Ab7',
          'A7', 'A#7/Bb7', 'B7',
          'C8'
        ],
        scales: {
          'C 调': ['C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5'],
          '#C 调': ['C#4/Db4', 'D#4/Eb4', 'F4', 'F#4/Gb4', 'G#4/Ab4', 'A#4/Bb4', 'C5','C#5/Db5'],
          'D 调': ['D4', 'E4', 'F#4/Gb4', 'G4', 'A4', 'B4', 'C#5/Db5','D5'],
          '#D 调': ['D#4/Eb4', 'F4', 'G4', 'G#4/Ab4', 'A#4/Bb4', 'C5', 'D5','D#5/Eb5'],
          'E 调': ['E4', 'F#4/Gb4', 'G#4/Ab4', 'A4', 'B4', 'C#5/Db5', 'D#5/Eb5','E5'],
          'F 调': ['F4', 'G4', 'A4', 'A#4/Bb4', 'C5', 'D5', 'E5','F5'],
          '#F 调': ['F#4/Gb4', 'G#4/Ab4', 'A#4/Bb4', 'B4', 'C#5/Db5', 'D#5/Eb5','F5','F#5/Gb5'],
          'G 调': ['G4', 'A4', 'B4', 'C5', 'D5', 'E5', 'F#5/Gb5','G5'],
          '#G 调': ['G#4/Ab4', 'A#4/Bb4', 'C5', 'C#5/Db5', 'D#5/Eb5', 'F5', 'G5','G#5/Ab5'],
          'A 调': ['A4', 'B4', 'C#5/Db5', 'D5', 'E5', 'F#5/Gb5', 'G#5/Ab5','A5'],
          '#A 调': ['A#4/Bb4', 'C5', 'D5', 'D#5/Eb5', 'F5', 'G5', 'A5','A#5/Bb5'],
          'B 调': ['B4', 'C#5/Db5', 'D#5/Eb5', 'E5', 'F#5/Gb5', 'G#5/Ab5', 'A#5/Bb5','B5'],
        },
        chords: {
          'C': ['C4', 'E4', 'G4'],
          'Cm': ['C4', 'D#4/Eb4', 'G4'],
          'D': ['D4', 'F#4/Gb4', 'A4'],
          'Dm': ['D4', 'F4', 'A4'],
          'E': ['E4', 'G#4/Ab4', 'B4'],
          'Em': ['E4', 'G4', 'B4'],
          'F': ['F4', 'A4', 'C5'],
          'Fm': ['F4', 'G#4/Ab4', 'C5'],
          'G': ['G4', 'B4', 'D5'],
          'Gm': ['G4', 'A#4/Bb4', 'D5'],
          'A': ['A4', 'C#5/Db5', 'E5'],
          'Am': ['A4', 'C5', 'E5'],
        },
        songName: "修炼爱情",
        songData: [
          { chord: "F", lyrics: "的心酸", newLine: true },
          { chord: "G", lyrics: "学会放好", newLine: true },
          { chord: "Em", lyrics: "以前的渴", newLine: true },
          { chord: "Am", lyrics: "望我们", newLine: true },
          { chord: "Dm", lyrics: "那些信仰", newLine: true },
          { chord: "G", lyrics: "要忘记多", newLine: true },
          { chord: "C", lyrics: "难", newLine: true },
        ],
        noteNames: [
          { name: '6', pitch: 'QHP' },
          { name: '升6降7', pitch: 'QHP' },
          { name: '7', pitch: 'QHP' },
          { name: '1', pitch: 'THP' },
          { name: '升1降2', pitch: 'THP' },
          { name: '2', pitch: 'THP' },
          { name: '升2降3', pitch: 'THP' },
          { name: '3', pitch: 'THP' },
          { name: '4', pitch: 'THP' },
          { name: '升4降5', pitch: 'THP' },
          { name: '5', pitch: 'THP' },
          { name: '升5降6', pitch: 'THP' },
          { name: '6', pitch: 'THP' },
          { name: '升6降7', pitch: 'THP' },
          { name: '7', pitch: 'THP' },
          { name: '1', pitch: 'DHP' },
          { name: '升1降2', pitch: 'DHP' },
          { name: '2', pitch: 'DHP' },
          { name: '升2降3', pitch: 'DHP' },
          { name: '3', pitch: 'DHP' },
          { name: '4', pitch: 'DHP' },
          { name: '升4降5', pitch: 'DHP' },
          { name: '5', pitch: 'DHP' },
          { name: '升5降6', pitch: 'DHP' },
          { name: '6', pitch: 'DHP' },
          { name: '升6降7', pitch: 'DHP' },
          { name: '7', pitch: 'DHP' },
          { name: '1', pitch: 'HP' },
          { name: '升1降2', pitch: 'HP' },
          { name: '2', pitch: 'HP' },
          { name: '升2降3', pitch: 'HP' },
          { name: '3', pitch: 'HP' },
          { name: '4', pitch: 'HP' },
          { name: '升4降5', pitch: 'HP' },
          { name: '5', pitch: 'HP' },
          { name: '升5降6', pitch: 'HP' },
          { name: '6', pitch: 'HP' },
          { name: '升6降7', pitch: 'HP' },
          { name: '7', pitch: 'HP' },
          { name: '1', pitch: 'MP' },
          { name: '升1降2', pitch: 'MP' },
          { name: '2', pitch: 'MP' },
          { name: '升2降3', pitch: 'MP' },
          { name: '3', pitch: 'MP' },
          { name: '4', pitch: 'MP' },
          { name: '升4降5', pitch: 'MP' },
          { name: '5', pitch: 'MP' },
          { name: '升5降6', pitch: 'MP' },
          { name: '6', pitch: 'MP' },
          { name: '升6降7', pitch: 'MP' },
          { name: '7', pitch: 'MP' },
          { name: '1', pitch: 'LP' },
          { name: '升1降2', pitch: 'LP' },
          { name: '2', pitch: 'LP' },
          { name: '升2降3', pitch: 'LP' },
          { name: '3', pitch: 'LP' },
          { name: '4', pitch: 'LP' },
          { name: '升4降5', pitch: 'LP' },
          { name: '5', pitch: 'LP' },
          { name: '升5降6', pitch: 'LP' },
          { name: '6', pitch: 'LP' },
          { name: '升6降7', pitch: 'LP' },
          { name: '7', pitch: 'LP' },
          { name: '1', pitch: 'DLP' },
          { name: '升1降2', pitch: 'DLP' },
          { name: '2', pitch: 'DLP' },
          { name: '升2降3', pitch: 'DLP' },
          { name: '3', pitch: 'DLP' },
          { name: '4', pitch: 'DLP' },
          { name: '升4降5', pitch: 'DLP' },
          { name: '5', pitch: 'DLP' },
          { name: '升5降6', pitch: 'DLP' },
          { name: '6', pitch: 'DLP' },
          { name: '升6降7', pitch: 'DLP' },
          { name: '7', pitch: 'DLP' },
          { name: '1', pitch: 'TLP' },
          { name: '升1降2', pitch: 'TLP' },
          { name: '2', pitch: 'TLP' },
          { name: '升2降3', pitch: 'TLP' },
          { name: '3', pitch: 'TLP' },
          { name: '4', pitch: 'TLP' },
          { name: '升4降5', pitch: 'TLP' },
          { name: '5', pitch: 'TLP' },
          { name: '升5降6', pitch: 'TLP' },
          { name: '6', pitch: 'TLP' },
          { name: '升6降7', pitch: 'TLP' },
          { name: '7', pitch: 'TLP' },
          { name: '1', pitch: 'QLP' },
        ],
        keysInGroup: [3, 12, 12, 12, 12, 12, 12, 12, 1],
        groupWidths: ['3.75%', '13.35%', '13.35%', '13.35%', '13.35%', '13.35%', '13.35%', '13.35%', '1.95%'],
        showKeyboard: true,
        showName: false,
        showInterval: false,
        isPcKey: false,
        isRecording: false,
        recorder: null,
        audioInput: null,
        audioDestination: null
      }
    },
    mounted() {
      this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
      this.initializeKeyboard();
      this.highlightPianoKeysForScale(Object.keys(this.scales)[0]);
      this.generateSongLyrics();
  
      // Add keyboard event listeners
      document.addEventListener('keydown', this.handleKeyDown);
      document.addEventListener('keyup', this.handleKeyUp);
  
      // Add click event listener for chord selection
      this.$el.addEventListener('click', (e) => {
        if (e.target.classList.contains('selectKey')) {
          const selectedIndex = this.$el.querySelector('#select-tuning option:selected')?.index || 0;
          this.highlightPianoKeys(e.target.textContent, selectedIndex);
        }
      });
  
      // 监听谱子播放事件
      this.$nextTick(() => {
        if (this.$refs.scoreEditor?.$refs.jianpuEditor) {
          console.log('Binding notePlayed event listener');
          this.$refs.scoreEditor.$refs.jianpuEditor.$on('notePlayed', this.handleNotePlayed);
        } else {
          console.warn('ScoreEditor or JianpuEditor refs not found');
        }
      });
    },
    beforeDestroy() {
      // 组件销毁时清理资源
      this.cleanupAudioResources();
      
      // 移除事件监听器
      document.removeEventListener('keydown', this.handleKeyDown);
      document.removeEventListener('keyup', this.handleKeyUp);
      
      // 移除谱子播放事件监听
      if (this.$refs.scoreEditor?.$refs.jianpuEditor) {
        this.$refs.scoreEditor.$refs.jianpuEditor.$off('notePlayed', this.handleNotePlayed);
      }
    },
    methods: {
      onPlay() {
        // 在播放前清除之前的高亮
        this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("active"));
        this.$refs.scoreEditor?.$refs.jianpuEditor?.playScore?.();
      },
      onStop() {
        // 停止播放时清除所有高亮
        this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("active"));
        this.$refs.scoreEditor?.$refs.jianpuEditor?.stopScore?.();
      },
      onOpen() {
        this.$refs.scoreEditor?.$refs.jianpuEditor?.openScore?.();
      },
      initializeKeyboard() {
        // Initialize keyboard layout and bindings
        this.mergedKeys = [...this.functionKeys, ...this.mainKeyboard, ...this.numpad];
      },
      highlightPianoKeys(chordName, mode) {
        this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("highlighted"));
        let keysToHighlight = this.chords[chordName];
        if(mode > 0) {
          let transposedChord = [];
          for (let note of keysToHighlight) {
            const index = this.pianoKeys.indexOf(note);
            if (index !== -1) {
              let transposedIndex = index + mode;
              if (transposedIndex < 0) {
                transposedIndex += this.pianoKeys.length;
              } else if (transposedIndex >= this.pianoKeys.length) {
                transposedIndex -= this.pianoKeys.length;
              }
              transposedChord.push(this.pianoKeys[transposedIndex]);
            } else {
              transposedChord.push(null);
            }
          }
          keysToHighlight = transposedChord;
        }
        keysToHighlight.forEach(key => {
          this.$el.querySelector(`.piano-key[data-id="${key}"]`)?.classList.add('highlighted');
        });
      },
      highlightPianoKeysForScale(scaleName) {
        this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("highlighted"));
        const keysToHighlight = this.scales[scaleName];
        keysToHighlight.forEach(key => {
          if (key.includes('#') || key.includes('b')) {
            const index = this.pianoKeys.indexOf(key);
            this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.add('highlighted');
          } else {
            this.$el.querySelector(`#${key}`)?.classList.add('highlighted');
          }
        });
      },
      handlePianoKeyClick(index) {
        if (!this.isCompute) {
          const id = this.pianoKeys[index];
          const audio = new Audio();
          let noteName;
          if (id.includes('/')) {
            noteName = id.split('/')[1];
          } else {
            noteName = id;
          }
          audio.src = `/audio/salamander/${noteName}.mp3`;
          audio.onerror = (e) => {
            console.error('Error loading audio:', e);
            this.$message.error('音频加载失败');
          };
          audio.currentTime = 0;
          audio.play().catch(error => {
            console.error('Error playing audio:', error);
            this.$message.error('音频播放失败');
          });
        } else {
          if (this.intervalList.length < 8) {
            const name = this.pianoKeys[index];
            if (this.intervalList.includes(name)) {
              this.intervalList = this.intervalList.filter(item => item !== name);
              this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.remove('highlighted');
            } else {
              this.intervalList.push(name);
              this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.add('highlighted');
            }
            this.updateIntervalList(this.intervalList);
          } else {
            this.$message.error('长度不要超过8个音符');
          }
        }
      },
      handleShowNameChange() {
        const spans = this.$el.querySelectorAll('.piano-key span');
        spans.forEach(span => {
          span.style.display = this.showName ? 'block' : 'none';
        });
      },
      handleShowKeyboardChange() {
        console.log('Keyboard visibility changed:', this.showKeyboard);
      },
      handleShowIntervalChange() {
        const intervalElements = this.$el.querySelectorAll('.interval');
        intervalElements.forEach(el => {
          el.style.display = this.showInterval ? 'block' : 'none';
        });
      },
      handleIsPcKeyChange() {
        // Visibility is handled by v-show
      },
      handleMIDISwitch() {
        if (this.showKeyboard) {
          if (navigator.requestMIDIAccess) {
            navigator.requestMIDIAccess()
              .then(this.onMIDISuccess)
              .catch(error => {
                console.error("无法访问MIDI设备:", error);
                this.$message.error('浏览器不支持MIDI!');
                this.showKeyboard = false;
              });
          } else {
            this.$message.error('浏览器不支持MIDI!');
            this.showKeyboard = false;
          }
        } else {
          this.$message.error('断开连接');
          this.disconnectMIDI();
          this.$el.querySelector('.mini-name').innerHTML = '';
        }
      },
      updateIntervalList(keys) {
        const intervalList = this.$el.querySelector('.interval-list');
        intervalList.innerHTML = '';
        
        keys.sort((a, b) => this.pianoKeys.indexOf(a) - this.pianoKeys.indexOf(b));
        
        keys.forEach((key, index) => {
          let nameArr;
          if (key.includes('#') || key.includes('b')) {
            nameArr = key.split("/")[0].split("");
            intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[1]}${nameArr[0]}<small>${nameArr[2]}</small></div>`;
          } else {
            nameArr = key.split("");
            intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[0]}<small>${nameArr[1]}</small></div>`;
          }
          
          if (index > 0) {
            const result = this.pianoKeys.indexOf(keys[index]) - this.pianoKeys.indexOf(keys[index - 1]);
            if (typeof this.intervals[result] === 'undefined') {
              this.$message.error('不要乱点跨度太大了!');
              this.$el.querySelector('.interval-sound:last-child')?.remove();
            } else {
              const intervalName = document.createElement('div');
              intervalName.className = 'interval-name';
              intervalName.textContent = this.intervals[result];
              this.$el.querySelector('.interval-sound:last-child')?.before(intervalName);
            }
          }
        });
      },
      generateSongLyrics() {
        const lyricsContainer = this.$el.querySelector('.lyrics-content');
        if (!lyricsContainer) return;
        
        lyricsContainer.innerHTML = '';
        this.songData.forEach(line => {
          if (line.newLine) {
            lyricsContainer.innerHTML += `
              <div class="line song-line">
                <p><span class="chord selectKey">${line.chord}</span></p>
                <p>${line.lyrics}</p>
              </div>`;
          } else {
            lyricsContainer.innerHTML += `
              <br/>
              <div class="line song-line">
                <p><span class="chord selectKey">${line.chord}</span> ${line.lyrics}</p>
              </div>`;
          }
        });
      },
      playTrack(index, key) {
        if (index === null || index === undefined || index < 0 || index >= this.pianoKeys.length) {
          console.warn('Invalid piano key index:', index);
          return;
        }
  
        if (!this.audioMap[index]) {
          const audio = new Audio();
          const id = this.pianoKeys[index];
          let noteName;
          if (id.includes('/')) {
            noteName = id.split('/')[1];
          } else {
            noteName = id;
          }
          audio.src = `/audio/salamander/${noteName}.mp3`;
          audio.onerror = (e) => {
            console.error('Error loading audio:', e);
            this.$message.error('音频加载失败');
            return;
          };
          
          const track = this.audioContext.createMediaElementSource(audio);
          const merger = this.audioContext.createChannelMerger(2);
          track.connect(merger);
          merger.connect(this.audioContext.destination);
          
          audio.play().catch(error => {
            console.error('Error playing audio:', error);
            this.$message.error('音频播放失败');
            return;
          });
          
          this.audioMap[index] = { audio, playing: true };
          this.highlightDiv(index, key);
        }
      },
      highlightDiv(index, key) {
        this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.add('active');
        this.$el.querySelector(`.key[data-code="${key}"]`)?.classList.add('active');
        this.$el.querySelector(`.pc-key-item:nth-child(${index + 1})`)?.classList.add('tantiao');
        this.activeDivs.push(index);
      },
      unhighlightDiv(index, key) {
        this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.remove('active');
        this.$el.querySelector(`.key[data-code="${key}"]`)?.classList.remove('active');
        this.$el.querySelector(`.pc-key-item:nth-child(${index + 1})`)?.classList.remove('tantiao');
        this.activeDivs = this.activeDivs.filter(item => item !== index);
      },
      stopAllTracks() {
        Object.values(this.audioMap).forEach(item => {
          const { audio, playing } = item;
          if (playing) {
            audio.addEventListener('ended', () => {
              audio.pause();
              audio.currentTime = 0;
            }, { once: true });
          } else {
            audio.pause();
            audio.currentTime = 0;
          }
        });
        this.audioMap = {};
        this.activeDivs.forEach(index => this.unhighlightDiv(index));
        this.activeDivs = [];
      },
      createTrack(src) {
        const audio = new Audio(`${this.domain}/mp3/${src}`);
        const track = this.audioContext.createMediaElementSource(audio);
        return { audio, track };
      },
      findPianoKeyByCode(num) {
        const mergedKeys = [...this.functionKeys, ...this.mainKeyboard, ...this.numpad];
        const key = mergedKeys.find(k => k.code === num.toString());
        return key?.pianoKey || null;
      },
      findPianoKeyByKey(index) {
        if (index) {
          const mergedKeys = [...this.functionKeys, ...this.mainKeyboard, ...this.numpad];
          const key = mergedKeys.find(k => k.pianoKey === index.toString());
          return key?.code || null;
        }
        return null;
      },
      handleKeyDown(e) {
        const activeElement = document.activeElement;
        if (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA') {
          return;
        }
        const key = e.which;
        const keyIndex = this.findPianoKeyByCode(key);
        if (keyIndex !== null && keyIndex !== undefined) {
          this.playTrack(keyIndex, key);
        }
      },
      handleKeyUp() {
        this.stopAllTracks();
      },
      onMIDISuccess(midiAccess) {
        console.log('MIDI ready!');
        this.midiAccess = midiAccess;
        const inputs = midiAccess.inputs;
  
        if (midiAccess.inputs.size > 0) {
          this.$message.success('连接成功!');
          inputs.forEach(input => {
            this.$el.querySelector('.mini-name').innerHTML = `<span class="state"></span>设备名称：${input.name}`;
            input.onmidimessage = this.getMIDIMessage;
          });
        } else {
          this.$message.error('未找到MIDI设备!');
          this.showKeyboard = false;
        }
  
        midiAccess.onstatechange = (event) => {
          const inputs = midiAccess.inputs.values();
          const inputsArray = Array.from(inputs);
  
          if (inputsArray.length === 0) {
            this.$message.error('MIDI设备已关闭!');
            this.$el.querySelector('.mini-name').innerHTML = '';
            this.showKeyboard = false;
          }
        };
      },
      onMIDIFailure(error) {
        this.$message.error('连接失败!');
        this.showKeyboard = false;
      },
      getMIDIMessage(event) {
        const currentTime = Date.now();
        const timeDiff = currentTime - this.lastProcessedTime;
  
        const command = event.data[0];
        const index = event.data[1];
        const velocity = event.data.length > 2 ? event.data[2] : 0;
        const key = this.findPianoKeyByKey(index - 21);
  
        switch (command) {
          case 144: // Note On
            if (velocity !== 0) {
              this.highlightDiv(index - 21, key);
            }
            break;
          case 248: // Note Off
            if (timeDiff >= 1000) {
              this.activeDivs.forEach(index => this.unhighlightDiv(index));
              this.lastProcessedTime = currentTime;
            }
            break;
        }
      },
      disconnectMIDI() {
        if (this.midiAccess) {
          this.midiAccess.inputs.forEach(input => {
            input.onmidimessage = null;
          });
          console.log("MIDI disconnected.");
        } else {
          console.warn("MIDI not connected.");
        }
      },
      handleShowNameChange() {
        const spans = this.$el.querySelectorAll('.piano-key span');
        spans.forEach(span => {
          span.style.display = this.showName ? 'block' : 'none';
        });
      },
      handleShowIntervalChange() {
        const intervalElements = this.$el.querySelectorAll('.interval');
        intervalElements.forEach(el => {
          el.style.display = this.showInterval ? 'block' : 'none';
        });
      },
      handleIsPcKeyChange() {
        // Visibility is handled by v-show
      },
      handleMIDISwitch() {
        if (this.showKeyboard) {
          if (navigator.requestMIDIAccess) {
            navigator.requestMIDIAccess()
              .then(this.onMIDISuccess)
              .catch(error => {
                console.error("无法访问MIDI设备:", error);
                this.$message.error('浏览器不支持MIDI!');
                this.showKeyboard = false;
              });
          } else {
            this.$message.error('浏览器不支持MIDI!');
            this.showKeyboard = false;
          }
        } else {
          this.$message.error('断开连接');
          this.disconnectMIDI();
          this.$el.querySelector('.mini-name').innerHTML = '';
        }
      },
      updateIntervalList(keys) {
        const intervalList = this.$el.querySelector('.interval-list');
        intervalList.innerHTML = '';
        
        keys.sort((a, b) => this.pianoKeys.indexOf(a) - this.pianoKeys.indexOf(b));
        
        keys.forEach((key, index) => {
          let nameArr;
          if (key.includes('#') || key.includes('b')) {
            nameArr = key.split("/")[0].split("");
            intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[1]}${nameArr[0]}<small>${nameArr[2]}</small></div>`;
          } else {
            nameArr = key.split("");
            intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[0]}<small>${nameArr[1]}</small></div>`;
          }
          
          if (index > 0) {
            const result = this.pianoKeys.indexOf(keys[index]) - this.pianoKeys.indexOf(keys[index - 1]);
            if (typeof this.intervals[result] === 'undefined') {
              this.$message.error('不要乱点跨度太大了!');
              this.$el.querySelector('.interval-sound:last-child')?.remove();
            } else {
              const intervalName = document.createElement('div');
              intervalName.className = 'interval-name';
              intervalName.textContent = this.intervals[result];
              this.$el.querySelector('.interval-sound:last-child')?.before(intervalName);
            }
          }
        });
      },
      generateSongLyrics() {
        const lyricsContainer = this.$el.querySelector('.lyrics-content');
        if (!lyricsContainer) return;
        
        lyricsContainer.innerHTML = '';
        this.songData.forEach(line => {
          if (line.newLine) {
            lyricsContainer.innerHTML += `
              <div class="line song-line">
                <p><span class="chord selectKey">${line.chord}</span></p>
                <p>${line.lyrics}</p>
              </div>`;
          } else {
            lyricsContainer.innerHTML += `
              <br/>
              <div class="line song-line">
                <p><span class="chord selectKey">${line.chord}</span> ${line.lyrics}</p>
              </div>`;
          }
        });
      },
      handleNotePlayed(note, cell) {
        console.log('Note played:', note, cell);
        // 将简谱音符转换为钢琴键索引
        const noteIndex = this.getPianoKeyIndex(note, cell);
        console.log('Piano key index:', noteIndex);
        if (noteIndex !== -1) {
          // 高亮对应的钢琴键
          const pianoKey = this.$el.querySelector(`.piano-key:nth-child(${noteIndex + 1})`);
          if (pianoKey) {
            pianoKey.classList.add('active');
            // 300ms 后移除高亮
            setTimeout(() => {
              pianoKey.classList.remove('active');
            }, 300);
          } else {
            console.warn('Piano key element not found for index:', noteIndex);
          }
        } else {
          console.warn('Invalid piano key index calculated for note:', note);
        }
      },
      getPianoKeyIndex(note, cell) {
        // 根据当前调式确定基准音符
        const scale = this.scales[this.currentScale];
        if (!scale) return -1;
  
        // 获取基准音符的索引（使用C4作为基准）
        const baseNoteIndex = this.pianoKeys.indexOf('C4');
        if (baseNoteIndex === -1) return -1;
  
        // 计算目标音符的索引
        // 简谱音符范围是 1-7，需要转换为 0-6
        const noteValue = (note - 1) % 7;
        
        // 获取当前调式的音阶
        const scaleNotes = scale.slice(0, 7); // 只取一个八度的音阶
        
        // 根据音阶中的音符位置计算实际索引
        const targetNote = scaleNotes[noteValue];
        if (!targetNote) return -1;
        
        // 找到目标音符在钢琴键数组中的索引
        const targetIndex = this.pianoKeys.indexOf(targetNote);
        if (targetIndex === -1) return -1;
  
        // 计算八度偏移
        let octaveOffset = 0;
        if (cell) {
          // 根据音高组计算八度偏移
          if (cell.pitch === '大字二组') {
            octaveOffset = -48; // 降低四个八度
          } else if (cell.pitch === '大字一组') {
            octaveOffset = -36; // 降低三个八度
          } else if (cell.pitch === '大字组') {
            octaveOffset = -24; // 降低两个八度
          } else if (cell.pitch === '小字组') {
            octaveOffset = -12; // 降低一个八度
          } else if (cell.pitch === '小字一组') {
            octaveOffset = 0; // 基准八度
          } else if (cell.pitch === '小字二组') {
            octaveOffset = 12; // 升高一个八度
          } else if (cell.pitch === '小字三组') {
            octaveOffset = 24; // 升高两个八度
          } else if (cell.pitch === '小字四组') {
            octaveOffset = 36; // 升高三个八度
          } else if (cell.pitch === '小字五组') {
            octaveOffset = 48; // 升高四个八度
          }
        }
        
        // 计算最终索引
        const finalIndex = targetIndex + octaveOffset;
        
        // 确保索引在有效范围内
        if (finalIndex < 0 || finalIndex >= this.pianoKeys.length) {
          console.warn('Invalid piano key index:', finalIndex, 'for note:', note, 'pitch:', cell?.pitch);
          return -1;
        }
        
        return finalIndex;
      },
      async toggleRecording() {
        if (!this.isRecording) {
          try {
            console.log('Starting audio initialization...');
            
            // 请求屏幕共享权限，包括系统声音
            const stream = await navigator.mediaDevices.getDisplayMedia({
              video: false,
              audio: {
                echoCancellation: true,
                noiseSuppression: true,
                sampleRate: 44100
              }
            });
            console.log('Display media stream obtained');

            // 创建音频上下文
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            console.log('AudioContext created:', audioContext.state);

            // 创建音频源
            const source = audioContext.createMediaStreamSource(stream);
            const destination = audioContext.createMediaStreamDestination();
            source.connect(destination);

            // 配置 RecordRTC
            const options = {
              type: 'audio',
              mimeType: 'audio/webm;codecs=opus',
              recorderType: RecordRTC.StereoAudioRecorder,
              numberOfAudioChannels: 2,
              desiredSampRate: 44100,
              bufferSize: 4096,
              timeSlice: 1000,
              ondataavailable: (blob) => {
                console.log('Recording data available:', blob);
              }
            };

            // 创建录音器
            this.recorder = new RecordRTC(destination.stream, options);
            console.log('Recorder created successfully');
            
            // 开始录音
            this.recorder.startRecording();
            console.log('Recording started');
            this.isRecording = true;
            
            // 保存音频上下文和流以便后续清理
            this.audioContext = audioContext;
            this.audioStream = stream;
            
            // 修改现有的音频播放方法，将音频输出连接到系统目标
            this.playTrack = (index, key) => {
              if (index === null || index === undefined || index < 0 || index >= this.pianoKeys.length) {
                console.warn('Invalid piano key index:', index);
                return;
              }

              if (!this.audioMap[index]) {
                try {
                  const audio = new Audio();
                  const id = this.pianoKeys[index];
                  let noteName;
                  if (id.includes('/')) {
                    noteName = id.split('/')[1];
                  } else {
                    noteName = id;
                  }
                  audio.src = `/audio/salamander/${noteName}.mp3`;
                  
                  audio.onerror = (e) => {
                    console.error('Error loading audio:', e);
                    this.$message.error('音频加载失败');
                    return;
                  };
                  
                  const track = this.audioContext.createMediaElementSource(audio);
                  track.connect(destination); // 连接到录音目标
                  
                  audio.play().catch(error => {
                    console.error('Error playing audio:', error);
                    this.$message.error('音频播放失败');
                    return;
                  });
                  
                  this.audioMap[index] = { audio, playing: true };
                  this.highlightDiv(index, key);
                } catch (err) {
                  console.error('Error in playTrack:', err);
                  this.$message.error('音频播放失败');
                }
              }
            };
            
          } catch (err) {
            console.error('Error initializing audio:', err);
            this.$message.error(`音频初始化失败: ${err.message}`);
            this.cleanupAudioResources();
          }
        } else {
          // 停止录音
          if (this.recorder) {
            console.log('Stopping recording...');
            this.recorder.stopRecording(() => {
              console.log('Recording stopped, getting blob...');
              const blob = this.recorder.getBlob();
              const url = URL.createObjectURL(blob);
              
              // 下载文件
              const a = document.createElement('a');
              a.href = url;
              a.download = `recording_${new Date().toISOString()}.webm`;
              a.click();
              
              // 清理
              URL.revokeObjectURL(url);
              this.cleanupAudioResources();
              console.log('Recording cleanup completed');
            });
          }
          
          this.isRecording = false;
        }
      },
      cleanupAudioResources() {
        console.log('Cleaning up audio resources...');
        
        // 停止所有音轨
        if (this.audioStream) {
          this.audioStream.getTracks().forEach(track => track.stop());
          this.audioStream = null;
        }
        
        // 清理音频上下文
        if (this.audioContext && this.audioContext.state !== 'closed') {
          try {
            this.audioContext.close();
            console.log('AudioContext closed successfully');
          } catch (err) {
            console.warn('Error closing AudioContext:', err);
          }
          this.audioContext = null;
        }

        // 清理录音器
        if (this.recorder) {
          this.recorder = null;
          console.log('Recorder cleaned up');
        }
        
        console.log('Audio resources cleanup completed');
      }
    }
  }
  </script>
  
  <style scoped>
  .preview-page {
    min-height: 100vh;
    background-color: #f5f7fa;
  }
  
  .preview-content {
    padding: 80px 10px 0px;
    margin: 0 auto;
  }
  
  .toolbar {
    width: 100%;
    background: var(--surface-color);
    box-shadow: var(--shadow-sm);
    padding: 12px 24px;
    display: flex;
    align-items: center;
    gap: 8px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 0;
    border-radius: 12px 12px 0 0;
  }
  
  .toolbar-divider {
    margin: 0 8px;
    height: 24px;
    background-color: var(--border-color);
  }
  
  .icon {
    width: 18px;
    height: 18px;
    vertical-align: middle;
    fill: currentColor;
    transition: transform 0.2s ease;
  }
  
  .el-button {
    width: 36px;
    height: 36px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    transition: all 0.2s ease;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid transparent;
  }
  
  .el-button:hover {
    color: var(--primary-color);
    background: rgba(37, 99, 235, 0.1);
    border-color: transparent;
    transform: translateY(-1px);
  }
  
  .el-button:active {
    transform: translateY(0);
  }
  
  .el-button .icon {
    font-size: 18px;
  }
  
  :deep(.el-tooltip__popper) {
    font-size: 12px;
    padding: 6px 12px;
    border-radius: 6px;
    background: var(--text-primary);
    color: white;
    box-shadow: var(--shadow-md);
  }
  
  .preview-score {
    background: var(--surface-color);
    border-radius: 0 0 12px 12px;
    box-shadow: var(--shadow-md);
    border: 1px solid var(--border-color);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    height: calc(100vh - 316px);
  }
  
  h1 {
    color: #222;
    margin-bottom: 24px;
  }
  
  .keyboard-name {
    margin-top: 20px;
    padding: 16px 24px;
    background: var(--surface-color);
    border-radius: 12px;
    box-shadow: var(--shadow-md);
    border: 1px solid var(--border-color);
    font-size: 16px;
    color: var(--text-primary);
  }
  
  .keyboard-name .name {
    font-weight: 500;
    color: var(--primary-color);
    margin-left: 8px;
  }
  
  @media (max-width: 768px) {
    .preview-content {
      padding: 80px 20px 20px;
    }
  }
  
  /* Piano and Keyboard Styles */
  .piano-main {
    height: calc(100vh - 200px);
    background: #1d1d1d;
    background-image: linear-gradient(to top, #adcefc, #96c4fd);
  }
  
  .piano-bottom {
    height: 175px;
    background: #000;
    width: 100%;
  }
  
  .piano-left {
    width: 80%;
    float: left;
    height: calc(100vh - 200px);
  }
  
  .piano-right {
    width: 20%;
    float: left;
    background: #fff;
    height: calc(100vh - 200px);
    overflow-y: auto;
    position: relative;
  }
  
  .piano-box {
    overflow: hidden;
  }
  
  .piano {
    display: flex;
    justify-content: space-between;
    background: #fff;
    width: 100%;
    border: 1px solid #000;
    border-top-width: 3px;
    box-sizing: border-box;
    height: 156px;
  }
  
  .piano-key {
    width: 2%;
    height: 152px;
    outline: 1px solid #444444;
    background-color: white;
    box-sizing: border-box;
    line-height: 240px;
    text-align: center;
    position: relative;
    border-radius: 0 0 2px 2px;
    border-bottom: 5px solid #eeeeee;
    cursor: pointer;
    -webkit-user-select: none;
  }
  
  .piano-key.black {
    border: none;
    color: #ccc;
    font-size: 12px !important;
    height: 90px;
    display: flex;
    align-items: flex-end;
    padding-bottom: 5px;
    width: 0.9%;
    height: 100px;
    margin: 0 -10px;
    background-color: #444444;
    z-index: 2;
    line-height: normal;
    color: #fff;
    writing-mode: inherit;
  }
  
  .piano-key:active {
    background: #000;
    color: #fff !important;
    border-bottom: 5px solid #000;
  }
  
  .piano-key.black:active {
    border-bottom: none;
  }
  
  .piano-key.active,
  .piano-key.active span:after {
    background: red;
    color: #fff !important;
    border-bottom: 5px solid red;
  }
  
  .piano-key:active span::after {
    color: #fff !important;
  }
  
  .piano-key span::after {
    position: absolute;
    bottom: 36px;
    left: 50%;
    margin-left: -5px;
    display: inline-block;
    width: 10px;
    font-size: 12px;
    line-height: 0;
    text-align: center;
    color: #000;
    writing-mode: tb;
    box-sizing: border-box;
  }
  
  .piano-key .LP::after {
    height: 4px;
    content: '.';
  }
  
  .piano-key .DLP::after {
    height: 6px;
    content: '..';
  }
  
  .piano-key .TLP::after {
    height: 8px;
    content: '...';
  }
  
  .piano-key .QLP::after {
    height: 10px;
    content: '....';
  }
  
  .piano-key .HP::after {
    height: 4px;
    bottom: 13px;
    content: '.';
  }
  
  .piano-key .DHP::after {
    bottom: 10px;
    height: 6px;
    content: '..';
  }
  
  .piano-key .THP::after {
    bottom: 8px;
    height: 8px;
    content: '...';
  }
  
  .piano-key .QHP::after {
    bottom: 8px;
    height: 8px;
    content: '....';
  }
  
  .piano-group {
    overflow: hidden;
    border: 1px solid #000;
    border-width: 0 0.1% 0 0.1%;
  }
  
  .piano-group li {
    float: left;
    width: auto;
    background: #ccc;
    font-size: 12px;
    color: #333;
  }
  
  .group {
    list-style: none;
    text-align: center;
    margin-top: 3px;
    margin-right: 0.1%;
    box-sizing: border-box;
    white-space: nowrap;
  }
  
  .group:last-child {
    margin-right: 0;
  }
  
  /* Keyboard Map Styles */
  .keyboard-box {
    position: relative;
    width: 100%;
    overflow: hidden;
  }
  
  .piano-bottom {
    height: 175px;
    background: #000;
    width: 100%;
  }
  
  .piano {
    display: flex;
    justify-content: space-between;
    background: #fff;
    width: 100%;
    border: 1px solid #000;
    border-top-width: 3px;
    box-sizing: border-box;
    height: 156px;
  }
  
  /* Main Keyboard Styles */
  .main-keyboard {
    grid-area: main-keyboard;
    display: grid;
    grid-template-columns: repeat(14, 1fr);
    grid-template-rows: repeat(4, 1fr);
    gap: 5px;
    border-radius: 5px;
    padding: 5px;
  }
  
  .numpad {
    grid-area: numpad;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(4, 1fr);
    gap: 5px;
    border-radius: 5px;
    padding: 5px;
  }
  
  #keyboard {
    display: grid;
    grid-template-areas:
      "function-keys function-keys"
      "main-keyboard numpad";
    gap: 9px;
    border-radius: 5px;
    background-image: linear-gradient(to top, #f9f9f9, #fff);
    padding: 10px;
    box-sizing: border-box;
    margin: 10px;
    font-size: 12px;
    color: #666;
    user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -webkit-user-select: none;
    margin-top: 30px;
    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.4);
  }
  
  .function-keys {
    grid-area: function-keys;
    display: flex;
    gap: 15px;
    border-radius: 5px;
    padding: 5px;
  }
  
  .key {
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 5px;
    border: 1px solid #ccc;
    background-color: #f0f0f0;
    cursor: pointer;
    transition: background-color 0.3s ease;
    padding: 9px;
    font-size: 14px;
    min-width: 30px;
    box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
  }
  
  .key:hover {
    background-color: #999;
    color: #fff;
  }
  
  .key.active {
    background: red;
    color: #fff;
    box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
    transform: translate(1px, 1px);
  }
  
  .key.colspan2 {
    grid-column: span 2;
    min-width: 60px;
  }
  
  .key.colspan9 {
    grid-column: span 9;
    min-width: 60px;
  }
  
  .key.rowspan2 {
    grid-row: span 2;
  }
  
  /* Switch Styles */
  .switch-box {
    position: relative;
    display: inline-block;
    width: 60px;
    height: 28px;
    margin-top: 6px;
    overflow: hidden;
  }
  
  .switch-input {
    display: none;
  }
  
  .switch-label {
    display: block;
    width: 100%;
    height: 100%;
    cursor: pointer;
    background: #ccc;
    border-radius: 17px;
    position: relative;
  }
  
  .switch-box .txt {
    display: inline-block;
  }
  
  .switch-label:before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 26px;
    height: 26px;
    background: white;
    border-radius: 50%;
    transition: 0.3s;
  }
  
  .switch-input:checked+.switch-label {
    background: #007bff;
  }
  
  .switch-input:checked+.switch-label:before {
    transform: translateX(34px);
  }
  
  .mini-name {
    padding: 20px 0 0 10px;
    color: #333;
  }
  
  .state {
    display: inline-block;
    width: 15px;
    height: 15px;
    margin-right: 5px;
    vertical-align: middle;
    background-color: #23d96e;
    border-radius: 100%;
    outline: 1px solid #f9f9f9;
  }
  
  /* Chord Type Styles */
  .chord-type {
    margin-top: 20px;
    padding: 0 15px;
  }
  
  .chord-type-title {
    width: 30px;
    text-align: center;
    font-size: 16px !important;
    background: #efa41b;
    color: #fff;
    font-weight: bold !important;
  }
  
  .chord-type-table {
    margin-top: 10px;
    background: #fff;
    width: 100%;
    border-collapse: collapse;
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid #f86e6e;
    outline: 2px solid #666;
    box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.4);
  }
  
  .chord-type-table td {
    border: 1px solid #eee;
    padding: 10px;
    font-size: 14px;
  }
  
  .chordp-type-item {
    display: inline-block;
    padding: 5px 10px;
    background: #f5f5f5;
    color: #666;
    margin-right: 5px;
    margin-bottom: 5px;
  }
  
  .preview-mode {
    pointer-events: none;
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
  }
  
  .preview-mode :deep(.cell) {
    cursor: default;
  }
  
  .preview-mode :deep(.measure-group) {
    cursor: default;
  }
  
  .preview-mode :deep(.selected-measure) {
    filter: none;
  }
  
  .record-button {
    position: relative;
    transition: all 0.3s ease;
    width: 48px !important;
    height: 48px !important;
    font-size: 20px;
    background: transparent !important;
    border: none !important;
  }
  
  .record-button:hover {
    transform: scale(1.1);
  }
  
  .record-button.recording .record-icon {
    color: #f56c6c;
    animation: blink 1s infinite;
  }
  
  .record-icon {
    font-size: 24px;
    color: #409EFF;
  }
  
  @keyframes blink {
    0% {
      opacity: 1;
    }
    50% {
      opacity: 0.5;
    }
    100% {
      opacity: 1;
    }
  }
  </style> 